import 'dart:async';
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:image/image.dart' as $ImageLib;

class $FileInfo {
  $FileInfo(
      {this.isImage = false, this.path, this.dataBytes, String? filename}) {
    if (filename == null) {
      if (this.isImage) {
        filename = _generateFileName(extension: this.dataBytes!.fileFormat);
      }
    }
    _filename = filename!;
  }

  final bool isImage;
  final String? path;
  final Uint8List? dataBytes;
  String? _filename;

  String get filename {
    if (_filename != null) {
      return _filename!;
    }
    return _generateFileName();
  }

  static String _generateFileName({String? extension}) {
    return '${DateTime.now().millisecondsSinceEpoch}.${extension ?? 'data'}';
  }
}

typedef PickFileCallback = Future<List<$FileInfo>?> Function();

class $File {
  static Future<List<MapEntry<String, MultipartFile>>?> filesToFormData(
      PickFileCallback pickFileCallback,
      {String parameterKey = 'file'}) async {
    List<$FileInfo>? fileList = await pickFileCallback();
    List<MapEntry<String, MultipartFile>>? retList;
    if (fileList != null) {
      retList = [];
      for ($FileInfo element in fileList) {
        dynamic data;
        if (element.dataBytes != null) {
          data = MapEntry(
              parameterKey,
              MultipartFile.fromBytes(element.dataBytes!,
                  filename: element.filename));
        } else {
          data = MapEntry(
              parameterKey, await MultipartFile.fromFile(element.path!));
        }
        retList.add(data);
      }
    }
    return retList;
  }
}

extension $Uint8List on Uint8List {
  String get fileFormat {
    Object? decoder = $ImageLib.findDecoderForData(this);
    if (decoder == null) {
      return 'data';
    }
    return decoder.runtimeType
        .toString()
        .replaceAll('Decoder', '')
        .toLowerCase();
  }
}
